package org.jing.ext.socket;

import org.jing.core.lang.BaseInitializer;
import org.jing.core.lang.JingException;
import org.jing.core.lang.JingInitializer;
import org.jing.core.lang.data.Carrier;
import org.jing.core.logger.JingLogger;
import org.jing.core.util.StringUtil;

import java.lang.reflect.ParameterizedType;

/**
 * Description: <br>
 *
 * @author bks <br>
 * @since 2024-07-08 <br>
 */
@SuppressWarnings("unchecked")
public class SocketServerInitializer extends BaseInitializer<SocketServerConfig> {
    private static final JingLogger LOGGER = JingLogger.getLogger(SocketServerInitializer.class);

    @Override public void execute() {
        LOGGER.info(">>>Socket Server Initializer Start<<<");
        DefaultSocketServerConfig defaultConfig = getConfig().getDefaultConfig();
        LOGGER.debug("default socket config: [{}]", defaultConfig);
        getConfig().getServersC().forEachChild(c$ -> createServer(defaultConfig, c$));
        LOGGER.info(">>>Socket Server Initializer End<<<");
    }

    private void createServer(DefaultSocketServerConfig defaultConfig, Carrier serverC) {
        String code = StringUtil.ifEmpty(serverC.getString(Const.KEY_CODE), serverC.getKey());
        LOGGER.info(">>>[{}] scanned", code);
        boolean enable = "true".equalsIgnoreCase(serverC.getString(Const.KEY_ENABLE));
        LOGGER.info("[{}].enable: [{}]", code, enable);
        if (!enable) return;
        serverC.setValue(Const.KEY_CODE, code);
        Carrier configC = Carrier.parseSerializableDto(defaultConfig);
        configC.putAll(serverC);
        String impl = serverC.getString(Const.KEY_IMPL);
        if (StringUtil.isEmpty(impl)) {
            throw new JingException("[{}] required", Const.KEY_IMPL);
        }
        LOGGER.info("[{}].impl: [{}]", code, impl);
        Class operatorClass;
        try {
            operatorClass = Class.forName(impl);
            if (!BaseSocketServerOperator.class.isAssignableFrom(operatorClass)) {
                throw new JingException("invalid [{}]: {}", Const.KEY_IMPL, impl);
            }
        }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
            throw new JingException(t);
        }
        Class<BaseSocketServerConfig> configClass = (Class<BaseSocketServerConfig>) ((ParameterizedType) operatorClass.getGenericSuperclass()).getActualTypeArguments()[0];
        LOGGER.info("[{}].config: [{}]", code, configClass.getName());
        BaseSocketServerConfig config = configC.serialize(configClass);
        SocketServerDispatcher dispatcher = SocketServerDispatcher.createDispatcher(config, (Class<BaseSocketServerOperator>) operatorClass);
        LOGGER.info("[{}].dispatcher: start", code);
        dispatcher.start();
    }

    public static void main(String[] args) {
        JingInitializer.initialize(SocketServerInitializer.class, JingInitializer.getRootConfig());
    }
}
